namespace SimpleTPL;

using System;
using System.Threading;

public class SimpleTask
{
    protected Action _action;
    public Exception _exception;
    protected bool _isCompleted;
    protected readonly object _syncLock = new object();
    protected List<Action<SimpleTask>> _continuations = new List<Action<SimpleTask>>();

    public bool IsCompleted
    {
        get { lock (_syncLock) return _isCompleted; }
    }
    
    public SimpleTaskAwaiter GetAwaiter()
    {
        return new SimpleTaskAwaiter(this);
    }

    public static SimpleAsyncMethodBuilder CreateAsyncMethodBuilder() => 
        SimpleAsyncMethodBuilder.Create();
    
    internal void SetResult()
    {
        lock (_syncLock)
        {
            _isCompleted = true;
            foreach (var continuation in _continuations)
            {
                try
                {
                    continuation(this);
                }
                catch { /* 忽略延续异常 */ }
            }
            _continuations = null;
        }
    }

    internal void SetException(Exception exception)
    {
        lock (_syncLock)
        {
            _exception = exception;
            _isCompleted = true;
            foreach (var continuation in _continuations)
            {
                try
                {
                    continuation(this);
                }
                catch
                {
                    /* 忽略延续异常 */
                }
            }

            _continuations = null;
        }
    }

    public SimpleTask(Action action)
    {
        _action = action ?? throw new ArgumentNullException(nameof(action));
    }
    
    // 添加一个无操作的空任务构造函数
    public SimpleTask()
    {
        _action = () => {}; // 默认空操作
    }

    internal void Execute()
    {
        try
        {
            _action();
        }
        catch (Exception ex)
        {
            _exception = ex;
        }
        finally
        {
            lock (_syncLock)
            {
                _isCompleted = true;
                foreach (var continuation in _continuations)
                {
                    try
                    {
                        continuation(this);
                    }
                    catch { /* 忽略延续异常 */ }
                }
                _continuations = null;
            }
        }
    }

    // 静态工厂方法
    public static SimpleTask Run(Action action)
    {
        var task = new SimpleTask(action);
        SimpleThreadPool.UnsafeQueueUserWorkItem(_ => task.Execute());
        return task;
    }

    public static SimpleTask<TResult> Run<TResult>(Func<TResult> function)
    {
        var task = new SimpleTask<TResult>(function);
        SimpleThreadPool.UnsafeQueueUserWorkItem(_ => task.Execute());
        return task;
    }

    public static SimpleTask Delay(int millisecondsDelay)
    {
        return Delay(TimeSpan.FromMilliseconds(millisecondsDelay));
    }

    public static SimpleTask Delay(TimeSpan delay)
    {
        var tcs = new SimpleTaskCompletionSource();
        var timer = new Timer(_ => tcs.SetResult(), null, delay, Timeout.InfiniteTimeSpan);
        return tcs.Task.ContinueWith(_ => timer.Dispose());
    }

    // 实例方法
    public SimpleTask ContinueWith(Action<SimpleTask> continuation)
    {
        if (continuation == null) throw new ArgumentNullException(nameof(continuation));

        var tcs = new SimpleTaskCompletionSource();

        lock (_syncLock)
        {
            if (_isCompleted)
            {
                SimpleTask.Run(() => { continuation(this); tcs.SetResult(); });
            }
            else
            {
                _continuations.Add(t => SimpleTask.Run(() => { continuation(t); tcs.SetResult(); }));
            }
        }

        return tcs.Task;
    }
}

public static class SimpleTaskEx
{
    public static void Await(this SimpleTask task, Action continuation)
    {
        var awaiter = task.GetAwaiter();
        if (awaiter.IsCompleted)
        {
            continuation();
        }
        else
        {
            awaiter.OnCompleted(continuation);
        }
    }

    public static void Await<T>(this SimpleTask<T> task, Action continuation)
    {
        var awaiter = task.GetAwaiter();
        if (awaiter.IsCompleted)
        {
            continuation();
        }
        else
        {
            awaiter.OnCompleted(continuation);
        }
    }
}